package com.lighting.common.core.util;

import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.*;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
public class JsonUtil {

    public static ObjectMapper mapper = createMapper();

    public static JavaType getCollectionType(Class<?> collectionClass, Class<?>... elementClasses) {
        return mapper.getTypeFactory().constructParametricType(collectionClass, elementClasses);
    }

    private static ObjectMapper createMapper() {
        ObjectMapper result = new ObjectMapper();
        // 设置输入时忽略在JSON字符串中存在但Java对象实际没有的属性
        result.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
        result.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
        // 设置输出时包含属性的风格
        result.setSerializationInclusion(Include.NON_EMPTY);
        result.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
        return result;
    }

    public static String toJSONString(Object obj) {
        if (obj == null) {
            return null;
        }
        String ret = "";
        try {
            ret = mapper.writeValueAsString(obj);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return ret;
    }

    public static JsonNode parseObject(String text) {
        try {
            return mapper.readTree(text);
        } catch (IOException e) {
            log.error(e.getMessage(), e);
            return null;
        }
    }

    public static <E> List<E> parseArray(String json, Class<?> elementClasses) {
        if (json == null) {
            return null;
        }
        try {
            JavaType javaType = getCollectionType(ArrayList.class, elementClasses);
            return mapper.readValue(json, javaType);
        } catch (IOException e) {
            log.warn("parse json string error:" + json, e);
            return null;
        }
    }

    public static <T> List<T> transform(List<?> list, Class<?> elementClasses) {
        if (list == null) {
            return null;
        }
        String json = JsonUtil.toJSONString(list);
        return parseArray(json, elementClasses);
    }

    public static <T> T parseObject(String json, Class<T> clazz) {
        if (json == null) {
            return null;
        }
        ObjectMapper mapper = JsonUtil.createMapper();
        try {
            return mapper.readValue(json, clazz);
        } catch (Exception e) {
            log.warn("parseObject error: {},{}", e.getMessage(), json);
            return null;
        }
    }

    public static <T> T parseObject(String json, TypeReference typeReference) {
        T t = null;
        if (mapper != null) {
            try {
                t = (T) mapper.readValue(json, typeReference);
            } catch (IOException e) {
                log.info("jackson反序列化失败：{}", e);
            }
        }
        return t;
    }

    /**
     * 将json格式转换成map对象
     */
    public static Map<String, Object> parseToMap(String json) {
        Map<String, Object> objMap = null;
        if (mapper != null) {
            try {
                objMap = mapper.readValue(json, new TypeReference<Map<String, Object>>() {
                });
            } catch (IOException e) {
                log.info("jackson反序列化失败：{}", e);
            }
        }
        return objMap;
    }

    public static <T> Map<String, T> parseToMap(String json, Class<T> valueType) {
        Map<String, T> objMap = null;
        if (mapper != null) {
            try {
                JavaType mapType = mapper.getTypeFactory().constructMapType(HashMap.class, String.class, valueType);
                objMap = mapper.readValue(json, mapType);
            } catch (IOException e) {
                log.info("jackson反序列化失败：{}", e);
            }
        }
        return objMap;
    }

    public static Map<String, String> parseToStringMap(String json) {
        Map<String, String> objMap = null;
        if (mapper != null) {
            try {
                objMap = mapper.readValue(json, new TypeReference<Map<String, String>>() {
                });
            } catch (IOException e) {
                log.info("jackson反序列化失败：{}", e);
            }
        }
        return objMap;
    }

    public static Map<String, Object> beanToMap(Object o) {
        String json = JsonUtil.toJSONString(o);
        return JsonUtil.parseToMap(json);
    }

    public static <T> T mapToBean(Map map, Class<T> clazz) {
        return mapper.convertValue(map, clazz);
    }

    public static <T> T mapToBean(Map map, TypeReference<T> typeReference) {
        return mapper.convertValue(map, typeReference);
    }
}
